#include <unistd.h>
#include <stdint.h>
#include <stdio.h>

typedef void (*init_call)(void);

extern init_call _init_start;
extern init_call _init_end;

#define _init __attribute__((unused, section(".prvinit")))
#define DECLARE_INIT(func) init_call _fn_##func _init = func

static void init_0(void)
{
	write(1, "init_0\n", sizeof("init_0\n"));
}
DECLARE_INIT(init_0);

static void init_1(void)
{
	printf("init_1\n");
}
DECLARE_INIT(init_1);

static void init_2(void)
{
	printf("init_2\n");
}
DECLARE_INIT(init_2);

/*
 * DECLARE_INIT like below:
 *  static init_call _fn_init_0 __attribute__((unused, section(".prvinit"))) = init_0;
 *  static init_call _fn_init_1 __attribute__((unused, section(".prvinit"))) = init_1;
 *  static init_call _fn_init_2 __attribute__((unused, section(".prvinit"))) = init_2;
*/

void do_initcalls(void)
{
	init_call *init_ptr = &_init_start;
	for (; init_ptr < &_init_end; init_ptr++) {
		printf("init address: %p\n", init_ptr);
		(*init_ptr)();
	}
}

int main(void)
{
	do_initcalls();

	return 0;
}
